#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <unistd.h>
#include <string.h>
#include "p12_loader.h"

#define SALT_BYTES 16
#define DERIVE_BYTES 32
#define DERIVE_ITERATIONS 200000

/* 从 salt 文件读取 */
int read_salt_hexfile(const char *path, unsigned char *out, size_t outlen) {
    FILE *f = fopen(path, "r");
    if (!f) return -1;
    char buf[128];
    if (!fgets(buf, sizeof(buf), f)) { fclose(f); return -1; }
    fclose(f);
    size_t len = strlen(buf);
    while (len && (buf[len-1]=='\n' || buf[len-1]=='\r')) buf[--len] = '\0';
    if (len/2 != outlen) return -1;
    for (size_t i=0; i<outlen; i++) {
        unsigned int hi, lo;
        if (sscanf(&buf[i*2], "%1x%1x", &hi, &lo) != 2) return -1;
        out[i] = (hi<<4) | lo;
    }
    return 0;
}

void hexdump(const unsigned char *buf, size_t len, char *out, size_t outlen) {
    static const char hex[] = "0123456789abcdef";
    if (outlen < len*2+1) return;
    for (size_t i=0; i<len; i++) {
        out[i*2] = hex[(buf[i] >> 4) & 0xF];
        out[i*2+1] = hex[buf[i] & 0xF];
    }
    out[len*2] = '\0';
}

int main(int argc, char **argv) {
    if (argc < 3) {
        fprintf(stderr, "usage: %s /path/to/sm2.p12 /path/to/p12_salt\n", argv[0]);
        return 1;
    }

    unsigned char salt[SALT_BYTES];
    if (read_salt_hexfile(argv[2], salt, sizeof(salt)) != 0) {
        fprintf(stderr, "读取 salt 文件失败\n");
        return 1;
    }

    char *secret = getpass("Enter passphrase: ");
    unsigned char derived[DERIVE_BYTES];
    const EVP_MD *md = EVP_get_digestbyname("sm3");
    if (!md) md = EVP_sha256(); // fallback

    if (!PKCS5_PBKDF2_HMAC(secret, strlen(secret),
                           salt, sizeof(salt),
                           DERIVE_ITERATIONS,
                           md, sizeof(derived), derived)) {
        fprintf(stderr, "派生口令失败\n");
        return 1;
    }

    char passhex[DERIVE_BYTES*2+1];
    hexdump(derived, sizeof(derived), passhex, sizeof(passhex));

    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();

    EVP_PKEY* key = load_private_key_from_pkcs12(argv[1], passhex);
    if (!key) {
        fprintf(stderr, "load failed\n");
        return 1;
    }
    fprintf(stderr, "loaded private key OK\n");
    EVP_PKEY_free(key);
    return 0;
}
